<?php

namespace app\Console;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;

//异步多进程curl 呵呵
class Content extends Command {
    public $max_precess = 4;
    public $mpid = 0;
    public $works = [];
    public $new_index = 0;
    public $fields = [  //这些字段每个页面有很多个,需要循环采集  这个属性中包含两个字段   title和url
                        'title' => [
                            'select' => '//*[@id="list"]/dl/dd/a',
                            'node'   => 'nodeValue',
                        ],
    ];

    // 命令行配置函数
    protected function configure() {
        // setName 设置命令行名称
        // setDescription 设置命令行描述
        $this->setName('http:con')->setDescription('Start Up!');
    }

    // 设置命令返回信息
    protected function execute(Input $input, Output $output) {
        try {
            $redis = new \Redis();
            //使用该方法创建连接，连接不会在调用close方法之后关闭，只有在进程结束之后该连接才会被关闭。
            $redis->connect('127.0.0.1', '6379');

            if($redis->lLen('con') == 0){
                //获取需要更新的小说
                $book = Db::name('con_0')
                    ->where('id>=300000 and id<400000 and content is null')
//                    ->where('id', '>=', 300000)
//                    ->where('id', '<', 400000)
//                    ->where('content is null')
                    ->select();
                dump($book);exit;
                foreach($book as $k=>$v){
                    $redis->lPush('con',json_encode($v));
                }
            }
            $redis->close();
            swoole_set_process_name('php-think:con');
            $this->mpid = posix_getpid();
            $this->Prun();
            $this->processWait();

        } catch (\RedisException $e) {
            die('ALL ERROR: ' . $e->getMessage());
        }

        $output->writeln("Con: Start" . date('Y-m-d H:i:s') . "\n");
    }

    public function Prun() {
        for ($i = 0; $i < $this->max_precess; $i++) {
            $this->CreateProcess();
        }
    }

    public function CreateProcess($index = null) {
        $process = new \swoole_process(function (\swoole_process $worker) use ($index) {
            if (is_null($index)) {
                $index = $this->new_index;
                $this->new_index++;
            }
            $redis = new \Redis();
            $redis->connect('127.0.0.1', '6379', 2);
            swoole_set_process_name(sprintf('php-think:son-%s', $this->new_index));
            for ($j = 0; $j < 10000; $j++) {
                $this->checkMpid($worker); //当前进程pid
                try{
                    $redis->ping();
                }catch (\RedisException $e){
                    echo $e->getMessage();
                    exit;
                }
                if($redis->lLen('con') != 0){
                    $v = $redis->rPop('con');
                }else{
                    dump("endTime: " . date("H:i:s") . 'maybe error or finished');
                    exit;
                }
                if (empty($v)) {
                    exit;
                }
                $v = json_decode($v, true);
                echo $v['id'] . "\n";
                $url = 'https://www.zwdu.com' . $v['url'];
                $html = curl_get($url);
                $content = getCon($html, '//div[@id="content"]', true);
                if(empty($content)){
                    echo 'getcon error';
                    continue;
                }
                $content = ltrim($content, '<div id="content">');
                $content = rtrim($content, '</div>');
                Db::name('con_0')->where('id', $v['id'])->update(['content' => addslashes($content), 'status' => 1]);

            }
            //exit('进程任务数量不足');
        }, false, false);
        $pid = $process->start();
        $this->works[$index] = $pid;
        return $pid;
    }

    public function checkMpid(&$worker) {
        if (!\swoole_process::kill($this->mpid, 0)) {
            // 这句提示,实际是看不到的.需要写到日志中
            $log = "endTime: " . date("H:i:s") . "--Master process exited, I [{$worker->pid}] also quit\n";
            echo $log;
            $worker->exit();

        }
    }

    public function rebootProcess($ret) {
        $pid = $ret['pid'];
        $index = array_search($pid, $this->works);
        if ($index !== false) {
            $index = intval($index);
            $new_pid = $this->CreateProcess($index);
            echo "rebootProcess: {$index}={$new_pid} Done\n";
            return;
        }
        throw new \Exception('rebootProcess Error: no pid');
    }

//清理僵尸进程

    public function processWait() {
        while (1) {
            if (count($this->works)) {
                $ret = \swoole_process::wait();
                if ($ret) {
                    $this->rebootProcess($ret);
                }
            } else {
                break;
            }
        }
    }

}